---
--类名: Map.lua
--创建日期: 2015-4-2
--创建人: 陈小虎
--功能描述: 
--修改内容：
--修改日期:   
--修改人:     
--修改备注: 
--
local Vector = require("app.utils.Vector")
--local Character = import("..models.Character")

local MapNodeTag = 118

local function _pause(node)
    if node:getTag()==MapNodeTag then
        node:pause()
    end

    node:walkChildren(function(child)
        _pause(child)
    end)
end

local function _resume(node)
    if node:getTag()==MapNodeTag then
        node:resume()
    end

    node:walkChildren(function(child)
        _resume(child)
    end)
end

local NodeGetPositionX = cc.Node.getPositionX
local NodeGetPositionY = cc.Node.getPositionY
local NodeGetPosition = cc.Node.getPosition
local NodeStopAllActions = cc.Node.stopAllActions
local NodeSetScale = cc.Node.setScale
local NodeRunAction = cc.Node.runAction
local NodeGetScale = cc.Node.getScale
local NodeToWorldPosition = cc.Node.toWorldPosition
local NodeToLocalPosition = cc.Node.toLocalPosition
local NodeSetPosition = cc.Node.setPosition
local NodeSetVisible = cc.Node.setVisible

local MathAbs = math.abs

-- 用来获取y坐标的元表的方法
local PathNodeM = {}
function PathNodeM:getY(x)
    local ret = nil
    if x >= self.minX and x <= self.maxX then
        if self.y then
            ret = self.y
        else
            ret = self.minY+((x-self.minX)/self.length) * self.height
        end
    end
    return ret
end

UserMapScaleString = "UserMapScale"

local Map = class("Map",function()
    local layer = display.newLayer()
    layer:setContentSize(cc.size(display.width,display.height))
    return layer
end)

function Map:ctor()
    local mapId = MapManager:getMapId()
    local mapPath = "scripts.mapconfig." .. "map_" .. mapId
    self.mMapConfig = app:loadResScript(mapPath)

    self:buildMap(mapId)
    self:setZoomScale(MapManager:getMapScale())

    local mapConfig = GD:queryMapById(mapId)
    local extentArray = string.split(mapConfig.mapExtent, ";")
    local length = #extentArray
    local arrExtent = {}
    for i = 1, length do
        local borderArray = string.split(extentArray[i], "|")
        if #borderArray >= 2 then
            table.insert(arrExtent, {left = tonumber(borderArray[1]), right = tonumber(borderArray[2])})
        end
    end

    -- 如果没有行走层，应该怎么走？TODO
    -- if #arrExtent == 0 then
    --     table.insert(arrExtent, {left = 0, right = 20000})
    -- end
    MapManager:forceBorder(arrExtent, PathNodeM)

    local function onNodeEvent(event)
        if "enter" == event then
            self:onEnter()
        elseif "exit" == event then
            self:onExit()
        elseif "cleanup" == event then
            self:onCleanup()
        end
    end
    self:registerScriptHandler(onNodeEvent) 
end

function Map:setLayerRatioxToConfig(params)
    if params.layerOrder >= 1 and params.layerOrder <= #self.mMapConfig.config.layer then
        self.mMapConfig.config.layer[params.layerOrder].ratiox =  params.ratiox
    end
end

---
--@function 建造地图
--
function Map:buildMap(mapId)

    -- 是否是星空谜棋地图，需要在路径位置填充元素
    local isChessMap = mapId == tonumber(S("starChessBattleMapId"))
    self._middlePathNodes = nil

    self.mAdjustHeight = display.height * 0.28

    --线路号集合
    self.mLines = Vector.new()
    --不同线移动速率
    self.mLinesMoveRate = Vector.new()
    --移动地板层集合
    self.mGrounds = {}

    --地图层集合
    self.mMapLayerVec = {}
    --视差节点集合
    self.mParallaxVec = Vector.new()

    --音效集合
    self.mSoundVec = Vector.new()
    --音乐集合
    self.mMusicsVec = Vector.new()
    --地图播放动画集合
    self.mAniVec = Vector.new()
    --pathNode集合
    self.mPathNodeVec = Vector.new()

    local mapC = self.mMapConfig.config

    -- 载入地图缩放配置
    MapManager:setDefaultScale(mapC.defaultScale or 0.75)
    MapManager:setMinScale(mapC.minScale or 0.5)
    MapManager:setMaxScale(mapC.maxScale or 1.0)
    -- local mapScale = app:getValue(UserMapScaleString, MapManager:getDefaultScale())
    -- if mapScale > MapManager:getMaxScale() or mapScale < MapManager:getMinScale() then
    --     mapScale = MapManager:getDefaultScale()
    -- end
    -- MapManager:setMapScale(mapScale)
    
    -- 每次进地图，都将镜头置为默认值
    local mapScale = MapManager:getDefaultScale()
    MapManager:setMapScale(mapScale)
    app:saveValue(UserMapScaleString, mapScale)

    --战斗层
    self.mBattleLayerZOrder = 6

    self.mMusicPath = mapC.music
    self.mBattleNormalColor = mapC.battleNormalColor or cc.c4b(150,150,150,255)
    self.mBattleMoreBlackColor = mapC.battleMoreBlackColor or cc.c4b(100,100,100,255)
    self.mBattleFullBlackColor = cc.c4b(3,3,3,255)

    local mapNode = cc.CSLoader:createNode(mapC.mapPath,true)
    print("mapPath = ",mapC.mapPath)
    ---[[


    -- 添加battle静态背景层(根据地图生成静态图片， 优化drawcall)
    self.mBattleStaticLayerParent = cc.Layer:create()
    self:addChild(self.mBattleStaticLayerParent)

    --添加背景层，不移动
    self.mBackgroundLayer = cc.Layer:create()
    self:addChild(self.mBackgroundLayer)
    
    self.mRainLayer = cc.Layer:create()
    self:addChild(self.mRainLayer)

    --添加缩放层 视差层添加到缩放层

    self.mZoomLayer = cc.Layer:create() --display.newColorLayer(cc.c4b(0,0,255,70))
    self.mZoomLayer:setName("Map.mZoomLayer")
    self.mZoomLayer:ignoreAnchorPointForPosition(false)
    self.mZoomLayer:setPosition(cc.p(display.width * 0.5,display.height * 0.3))
    self.mZoomLayer:setAnchorPoint(cc.p(0.5,0.3))
    self:addChild(self.mZoomLayer)
    self:saveZoomLayerOriginalPos(cc.p(self.mZoomLayer:getPosition()))

    --创建移动视差节点
    self.mParallaxNode = cc.ParallaxNode:create()
    self.mParallaxNode:setName("Map.mParallaxNode")
    MapManager:setParallaxNode(self.mParallaxNode)
    self.mZoomLayer:addChild(self.mParallaxNode,1000)

    --添加调试路径层
    self.mDebugPathLayer = cc.Layer:create()
    self.mParallaxNode:addChild(self.mDebugPathLayer,1,cc.p(1,1),cc.p(0,0))

    self.cachedZoomLayers = {}
    self.mMapLayerVec = {}

    local maxZ = 0
    local groundZ = 0
    for k, layerConfig in pairs(mapC.layer) do
        local zOrder = layerConfig.zOrder

        if maxZ < zOrder then
            maxZ = zOrder
        end
        
        local node = mapNode:getChildByName(layerConfig.layerName)
        if node then
            node:setTagDeep(MapNodeTag)
            node:setTouchSwallowEnabled(false)
            mapNode:removeChild(node,false)
            --node:setParent(nil)

            if layerConfig.ratiox == 0 and layerConfig.zOrder == 0 then
                self.mBackgroundLayer:addChild(node)
            elseif layerConfig.layerName == "rain" then
                self.mRainLayer:addChild(node)
            else
                local layer = cc.Layer:create()--cc.LayerColor:create(cc.c4b(255,0,0,0),display.width,display.height)
                layer:setName("MapLayerBase."..layerConfig.layerName)
                if layerConfig.layerName == "ground_B" then
                    self.mGroudBLayer = layer
                elseif layerConfig.layerName == "jvyuan" then
                    -- 这是歌剧院的bg
                    self._theatreBg = node:getChildByName("woerdan_1")
                end
                layer:ignoreAnchorPointForPosition(false)
                layer:setPosition(cc.p(display.width / 2,display.height / 2))

                self.mZoomLayer:addChild(layer,zOrder)


                if layerConfig.defaultScale then
                    NodeSetScale(layer, layerConfig.defaultScale)
                end
                if layerConfig.minScale and layerConfig.maxScale and layerConfig.minScale == layerConfig.maxScale then
                    NodeSetScale(layer, layerConfig.minScale)
                end

                local offsetX = (1 - layerConfig.ratiox) * display.width

                local parallaxNode = cc.ParallaxNode:create()
                parallaxNode:setName("LayerBaseParallaxNode."..layerConfig.layerName)
                parallaxNode:addChild(node,0,cc.p(layerConfig.ratiox,1),cc.p(offsetX,0))
                layer:addChild(parallaxNode)

                self.mParallaxVec:add(parallaxNode)
                table.insert(self.mMapLayerVec, layer)
                self.cachedZoomLayers[layerConfig.layerName]=layer

                if layerConfig.fade then
                    display.setCascadeOpacityEnabled(layer,true)
                    display.setCascadeColorEnabled(layer,true)
                end

                if layerConfig.pathNode then--路径节点
                    for k1, pathNodeConfig in ipairs(layerConfig.pathNode) do
                        --local ground = self.mParallaxNode:getChildByName(v.layerName)
                        local pathNode = node:getChildByName(pathNodeConfig.name)
                        if pathNode then
                            -- 如果是星空谜棋地图，缓存ground_M下面的路径节点 
                            if isChessMap and layerConfig.layerName == "ground_M" then
                                self._middlePathNodes = pathNode:getChildren()
                                print("self._middlePathNodes", #self._middlePathNodes)
                            end

                            local pathZOrder = pathNodeConfig.pathZOrder or 0
                            local ground = cc.Layer:create()
                            ground:setName("GroundBase."..layerConfig.layerName)
                            parallaxNode:addChild(ground,pathZOrder,cc.p(1,1),cc.p(0,0))
       
                            self:buildPath(ground,pathNode, pathNodeConfig.line,node)

                            self.mLines:add(pathNodeConfig.line)
                            self.mLinesMoveRate[tonumber(pathNodeConfig.line)] = layerConfig.ratiox
                            self.mGrounds[tonumber(pathNodeConfig.line)] = ground

                            local pathNodeInfo = {}
                            pathNodeInfo.line = pathNodeConfig.line
                            pathNodeInfo.name = pathNodeConfig.name
                            pathNodeInfo.roleScale = pathNodeConfig.roleScale or 1.0

                            self.mPathNodeVec:add(pathNodeInfo)

                            if pathNodeConfig.line == Constant.BattleGroundLineNumber then
                                self.mBattleLayerZOrder = zOrder
                                self.mBattleParallaxNode = parallaxNode
                            end
                        end
                    end
                end

                if layerConfig.sizeNode then--地图尺寸节点
                    local groundSize = node:getChildByName(layerConfig.sizeNode)
                    MapManager:setMapWidth(groundSize:getContentSize().width)
                    MapManager:setMapHeight(groundSize:getContentSize().height)
                    groundSize:setVisible(false)
                    groundZ = zOrder

                    self.mNpcLayer = cc.Layer:create()
                    parallaxNode:addChild(self.mNpcLayer,-1,cc.p(1,1),cc.p(0,0))
                end
            end
            -- node:release()
        else
            print("do not have layer ", layerConfig.layerName)
        end
    end
    --]]

    self.mMaxZ = maxZ

    --调整路径层zOrder
    self.mParallaxNode:reorderChild(self.mDebugPathLayer,maxZ - 1)
    self.mParallaxNode:reorderChild(self.mRainLayer,maxZ) --TODO: ???  mRainLayer不是mParallaxNode的孩子节点


    local pathNode = self:getPathNode(2)
    if pathNode then
        MapManager:setGroundRoleScale(Constant.HeroScale * pathNode.roleScale)
        MapManager:setGroundNpcScale(Constant.NpcScale * pathNode.roleScale)
        MapManager:setGroundBossScale(Constant.BossScale * pathNode.roleScale)
        MapManager:setGroundMercenaryScale(Constant.MercScale * pathNode.roleScale)
    else
        MapManager:setGroundRoleScale(Constant.HeroScale)
        MapManager:setGroundNpcScale(Constant.NpcScale)
        MapManager:setGroundBossScale(Constant.BossScale)
        MapManager:setGroundMercenaryScale(Constant.MercScale)
    end

    local groundNode = self:getGroundByLine(Constant.BattleGroundLineNumber)
    groundNode:setName("Map.BattleGroundLine")
    MapManager:setGroundNode(groundNode)
    self.mBattleGround = groundNode

    self:addListners()

    self:setNodeEventEnabled(true)
end

-- 动态生成战斗背景层
function Map:startgenBattleStaticBg()
    if self.mBattleStaticDrawLayers  then
        return
    end
    local drawLayers = {}
    self.mRainLayer:setVisible(false)
    self.mBattleStaticLayerParent:removeAllChildren()
    local renderTexture = cc.RenderTexture:create(display.width,display.height)
    renderTexture:setPosition(display.width/2,display.height/2)
    self.mBattleStaticLayerParent:addChild(renderTexture)

    table.insert(drawLayers, self.mBackgroundLayer)
    table.sort(self.mMapLayerVec, function(a, b)
        local zOrderA = a:getLocalZOrder()
        local zOrderB = b:getLocalZOrder()
        return zOrderA < zOrderB
    end)

    for k, v in ipairs(self.mMapLayerVec) do
        if string.find( v:getName(),"MapLayerBase.BG") then
            table.insert(drawLayers, v)
        end
    end

    self.mBattleStaticDrawLayers = drawLayers
    renderTexture:begin()
    for k, v in pairs(self.mBattleStaticDrawLayers) do
        v:visit()
        v:setVisible(false)
    end
    renderTexture:endToLua()
end

-- 删除静态图片
function Map:stopgenBattleStaticBg()
    if not self.mBattleStaticDrawLayers then
        return
    end
    self.mBattleStaticLayerParent:removeAllChildren()
    self.mRainLayer:setVisible(true)
    for k, v in pairs(self.mBattleStaticDrawLayers) do
        v:setVisible(true)
    end
    self.mBattleStaticDrawLayers = nil
end

-- 更新歌剧院背景
function Map:updateTheatreBg(path)
    self._theatreBg:setTexture(path)
end

-- ground_M 的pathNodes
function Map:getMiddlePathNodes()
    return self._middlePathNodes
end

-- 播放星空谜棋目标点特效
function Map:playChessAction(posX, posY, isMe)
    if not self._middlePathNodes then return end
    if not self._chessTargetNode then
        local parent = self._middlePathNodes[1]:getParent()
        local node = cc.CSLoader:createNode(Res.ChessTargetNode, true)
        parent:addChild(node)
        self._chessTargetNode = node
    end

    local node = self._chessTargetNode
    node:setVisible(true)
    node:setPosition(posX, posY)
    node:findChild("Panel/my"):setVisible(isMe)
    node:findChild("Panel/foe"):setVisible(not isMe)
    node:getTimeline():gotoFrameAndPlay(0, true)
end
-- 停止星空谜棋目标点特效，停止之后会播放额外的特效
-- render = ChessRender
-- cb = 回调
function Map:stopChessAction(render, cb)
    if self._chessTargetNode then
        self._chessTargetNode:setVisible(false)
        self._chessTargetNode:getTimeline():pause()
    end

    if render then
        local cell = render:getData()
        local armature = self:_getChessTraggerArmature(cell:getCellFx())
        armature:setPosition(render:getPosition())
        armature:setVisible(true)

        armature:play("attack", 1, function(sender)
                sender:setVisible(false)
                executeFunc(cb)
            end)
    end
end

function Map:_getChessTraggerArmature(name)
    self._armatures = self._armatures or {}
    if not self._armatures[name] then
        local params = {
            armatureName = name,
            path = Res.ChessTriggerEfcPath
        }
        local parent = self:getGroundByLine(2)

        local Armature = app:getClass("Armature")
        local armature = Armature.create(params)
        armature:setScale(1.5)
        parent:addChild(armature, 5)
        self._armatures[name] = armature
    end
    return self._armatures[name]
end

function Map:onEnter()
    --test code by will
    --[[
    local Filters = {
        -- colors
        {"GRAY",{0.2, 0.3, 0.5, 0.1}},
        {"RGB",{1, 0.5, 0.3}},
        {"HUE", {90}},
        {"BRIGHTNESS", {0.3}},
        {"SATURATION", {0}},
        {"CONTRAST", {2}},
        {"EXPOSURE", {2}},
        {"GAMMA", {2}},
        {"HAZE", {0.1, 0.2}},
    }
    local filters,params = unpack(Filters[1])
    self:setFilter(filters,params)
    ]]
end

-- exit 之后的回调
function Map:setExitCB(cb)
    self._exitCB = cb
end

function Map:onExit()

    self:stopAllSounds(false)
    
    for i,handle in ipairs(self._fieldHandles) do
        FieldManager:removeEventListener(handle)
    end
    for i,handle in ipairs(self._mapHandles) do
        MapManager:removeEventListener(handle)
    end
    for i,handle in ipairs(self._npcHandles) do
        NpcManager:removeEventListener(handle)
    end
    for i,handle in ipairs(self._dungeonNpcHandles) do
        DungeonManager:removeEventListener(handle)
    end

    executeFunc(self._exitCB)
end

function Map:onCleanup()
    self:setFilter(nil)
    if not cc.isDead(self.taskSeq) then
        MapManager.taskSeq:removeFromParent(true)
        MapManager.taskSeq = nil
    end
end

function Map:addListners()
    self._dungeonNpcHandles = {}
    self._dungeonNpcHandles[#self._dungeonNpcHandles + 1] = DungeonManager:addEventListener("map_DeleteNpc", function(event)
        self:deleteNpcFromGround(event.npc,event.line)
    end)


    self._npcHandles = {}
    self._npcHandles[#self._npcHandles + 1] = NpcManager:addEventListener("map_DeleteNpc", function(event)
        self:deleteNpcFromGround(event.npc,event.line)
    end)

    self._fieldHandles = {}
    self._fieldHandles[#self._fieldHandles + 1] = FieldManager:addEventListener("map_delete_character",function(event)
        self:removeCharacter(event.character,event.cleanup)
    end)
    self._fieldHandles[#self._fieldHandles + 1] = FieldManager:addEventListener("map_add_mercenary",function(event)
        self:addMercenary(event.merc)
    end)

    self._mapHandles = {}
    self._mapHandles[#self._mapHandles + 1] = MapManager:addEventListener("map_reset_focus", function(event)
        self:resetFocus()
    end)

    self._mapHandles[#self._mapHandles + 1] = MapManager:addEventListener("map_force_camera_zoom_to_runmax",function(event)
        self:forceCameraZoomToRunMax(event.params.resetPause,event.params.time,event.params.call)
    end)

    self._mapHandles[#self._mapHandles + 1] = MapManager:addEventListener("map_force_camera_zoomout_to_dest",function(event)
        self:forecCameraZoomOutToDest(event.params.time,event.params.dstScale,event.params.funcOver,event.params.flag)
    end)
    
    self._mapHandles[#self._mapHandles + 1] = MapManager:addEventListener("map_force_camera_zoom_to_dest",function(event)
        self:forceCameraZoomToDest(event.params.time,event.params.dstScale,event.params.call)
    end)
    self._mapHandles[#self._mapHandles + 1] = MapManager:addEventListener("map_stop_parallax_actions",function(event)
        self:stopParallaxActions()
    end)
    self._mapHandles[#self._mapHandles + 1] = MapManager:addEventListener("map_save_map_layer_scale",function(event)
        self:saveMapLayerScale()
    end)
    
    self._mapHandles[#self._mapHandles + 1] = MapManager:addEventListener("map_back_to_savemap_layer_scale",function(event)
        self:backToSaveMapLayerScale(event.params.time,event.params.callback)
    end)
    self._mapHandles[#self._mapHandles + 1] = MapManager:addEventListener("map_map_offset_with_center",function(event)
        self:mapOffsetWithCenter(event.params.time,event.params.offsetx,event.params.offsety,event.params.scale)
    end)
    
    self._mapHandles[#self._mapHandles + 1] = MapManager:addEventListener("map_back_map_offset_to_center",function(event)
        self:backMapOffsetToCenter(event.params.time,event.params.callback)
    end)
    
    self._mapHandles[#self._mapHandles + 1] = MapManager:addEventListener("map_stop_camera_for_battle",function(event)
        self:stopCameraForBattle(event.params.stop)
    end)
    self._mapHandles[#self._mapHandles + 1] = MapManager:addEventListener("map_fade_node_visibility",function(event)
        self:fadeNodeVisibility(event.params.visible)
    end)
    self._mapHandles[#self._mapHandles + 1] = MapManager:addEventListener("map_set_focus_character_for_init",function(event)
        self:setFocusCharacterForInit(event.params.character)
    end)
    self._mapHandles[#self._mapHandles + 1] = MapManager:addEventListener("map_set_focus_character_not_init",function(event)
        self:setFocusCharacterNotInit(event.params.character)
    end)
    self._mapHandles[#self._mapHandles + 1] = MapManager:addEventListener("map_force_camera_zoom_in",function(event)
        self:forceCameraZoomIn(event.params.callback,event.params.time,event.params.scale)
    end)
    self._mapHandles[#self._mapHandles + 1] = MapManager:addEventListener("map_fade_map_node",function(event)
        self:fadeNodeOpacity(event.params.time,event.params.back)
    end)
    self._mapHandles[#self._mapHandles + 1] = MapManager:addEventListener("map_set_focus_character",function(event)
        self:setFocusCharacter(event.params.character)
    end)
    self._mapHandles[#self._mapHandles + 1] = MapManager:addEventListener("map_set_focus_battle_actor",function(event)
        self:setFocusBattleActor(event.params.actor, event.params.needInit)
    end)
    self._mapHandles[#self._mapHandles + 1] = MapManager:addEventListener("map_set_battle_camera_clamp",function(event)
        self:setBattleCameraClamp(event.params.leftClampPosX, event.params.rightClampPosX)
    end)
    self._mapHandles[#self._mapHandles + 1] = MapManager:addEventListener("map_back_npc_focus_to_old_character",function(event)
        self:backNpcFocusToOldCharacter(event.params.time,event.params.callback)  
    end)
    self._mapHandles[#self._mapHandles + 1] = MapManager:addEventListener("map_map_to_normal_color",function(event)
        self:toOriginColor()
    end)
    self._mapHandles[#self._mapHandles + 1] = MapManager:addEventListener("map_play_map_music",function(event)
        self:startAllSounds()
    end)
    self._mapHandles[#self._mapHandles + 1] = MapManager:addEventListener("map_stop_map_music",function(event)
        self:stopAllSounds()
    end)
    self._mapHandles[#self._mapHandles + 1] = MapManager:addEventListener("map_init_camera",function(event)
        self:initCamera()
    end)
    self._mapHandles[#self._mapHandles + 1] = MapManager:addEventListener("map_set_mask",function(event)
        self:setMapMask(event.params.color,event.params.fadeTime)
    end)
    self._mapHandles[#self._mapHandles + 1] = MapManager:addEventListener("map_add_character",function(event)
        self:addCharacter(event.character,event.zOrder)
    end)

end

function Map:setMapMask(color,fadeTime)
    self._mapMaskFadeTime = fadeTime or 0
    if self._mapMaskFadeTime > 0 then
        self._startMapMask = true
        self._tColor = color
        self._oColors = {}
        self._startMapMaskTime = app:getTime()
        for i = 1,self.mParallaxVec:size() do
            local node = self.mParallaxVec:get(i)
            table.insert(self._oColors,node:getColor())
        end
    else
        self._startMapMask = false
        for i = 1,self.mParallaxVec:size() do
            local node = self.mParallaxVec:get(i)
            display.setColor(node,color)
        end 
    end
end

function Map:updateMapMask(dt)
    if not self._startMapMask then return end

    local iTime = app:getTime() - self._startMapMaskTime
    if iTime > self._mapMaskFadeTime then
        iTime = self._mapMaskFadeTime
    end
    local percent = iTime / self._mapMaskFadeTime
    for i = 1,self.mParallaxVec:size() do
        local node = self.mParallaxVec:get(i)
        local oColor = self._oColors[i]
        if oColor and node then
            local ir = (self._tColor.r - oColor.r) * percent
            local ig = (self._tColor.g - oColor.g) * percent
            local ib = (self._tColor.b - oColor.b) * percent
            local cColor = {r = oColor.r + ir,g = oColor.g + ig,b = oColor.b + ib}
            display.setColor(node,cColor)
        end
    end

    if iTime == self._mapMaskFadeTime then
        self._startMapMask = false
    end
end

function Map:getBattleNormalColor()
    return self.mBattleNormalColor
end

function Map:getBattleMoreBlackColor()
    return self.mBattleMoreBlackColor
end

function Map:startAllSounds()
    self.mPauseAllSounds = false
    self:playMusic()
    self:playMutiMusics()
    self:playSurroundingSounds()
end

function Map:stopAllSounds(fade)
    self.mPauseAllSounds = true
    self:stopMusic(fade)
    self:stopMutiMusics()
    self:stopSurroundingSounds()
end

function Map:playMusic()
    if self.mMusicPath and not AM.isAudioInPlaying(self.musicId) then
        local pos = self.musicPosition or 0 
        self.musicId = AM.play(self.mMusicPath,true,AM.TagMusic)
        if self.musicId then
            AM.setCurrentTime(self.musicId,pos)
            AM.fadeIn(self.musicId,1)
        end
    end
end

function Map:stopMusic(fade)
    if AM.isAudioInPlaying(self.musicId) then
        self.musicPosition = AM.getCurrentTime(self.musicId)
        if fade then
            AM.fadeOut(self.musicId,1)
        else
            AM.stop(self.musicId)
        end
        self.musicId=nil
    end
end

function Map:setMusicVolume(volume)
    if AM.isAudioInPlaying(self.musicId) then
        AM.setVolume(self.musicId,volume)
    end
end

function Map:playMutiMusics()
    --多背景音
    if self.mMapConfig.config.musics then
        for i,v in ipairs(self.mMapConfig.config.musics) do
            local audioId = AM.play(v.music,true,AM.TagMusic)
            if audioId then
                AM.setVolume(audioId,v.volume)
                self.mMusicsVec:add(audioId)
            end
        end
    end
end

function Map:stopMutiMusics()
    for i = 1,self.mMusicsVec:size() do
        local audioId = self.mMusicsVec:get(i)
        if audioId then
            AM.stop(audioId)
        end
    end
    self.mMusicsVec:clear()
end

function Map:playSurroundingSounds()
    --环境音
    if self.mMapConfig.config.surroundingSounds then
        for i,v in ipairs(self.mMapConfig.config.surroundingSounds) do
            local sound = {}
            sound.sound = v.sound
            sound.sourcex = v.sourcex
            sound.range = v.range
            self.mSoundVec:add(sound)
        end
    end
end

function Map:stopSurroundingSounds()
    for i = 1, self.mSoundVec:size() do
        local sound = self.mSoundVec:get(i)
        if sound.audioId then
            AM.stop(sound.audioId)
            sound.audioId=nil
        end
    end
    self.mSoundVec:clear()
end

function Map:stopSurroundingSounds()
    for i = 1, self.mSoundVec:size() do
        local sound = self.mSoundVec:get(i)
        if sound.audioId then
            AM.stop(sound.audioId)
            sound.audioId=nil
        end
    end
end

---
--@function 测试用，更改mapconfig，刷新
--
function Map:clear()
    self:removeAllChildren()
    self.mFocusCharacter = nil
end

function Map:getBattleLayer()
    return self.mBattleLayer
end

function Map:getBattleMaskLayer()
    return self.mBattleMaskLayer
end

function Map:getPathNode(line)
    for i = 1, self.mPathNodeVec:size() do
        local pathNode = self.mPathNodeVec:get(i)
        if tonumber(pathNode.line) == tonumber(line) then
            return pathNode
        end
    end
    return nil
end

function Map:getLayerDefaultConfig(layerName)

    for k,v in pairs(self.mMapConfig.config.layer) do
        if v.layerName == layerName then
            return v
        end
    end

    return nil
end

function Map:getLayerConfigByLine(line)
    for k,v in pairs(self.mMapConfig.config.layer) do
        if v.pathNode then
            for i,v1 in ipairs(v.pathNode) do
                if v1.line == line then
                    return v
                end
            end
        end
    end
    return nil
end

function Map:zoom(zoomConfig)
    for k,v in pairs(zoomConfig) do

        local layer = self.cachedZoomLayers[v.layerName]
        if layer and v.time then
            local rate = v.rate or 1
            local scale = v.scale or 1

            local scaleAction = cc.ScaleTo:create(v.time,scale)
            local spawnAction = cc.Spawn:create(scaleAction,cc.MoveTo:create(v.time,cc.p(NodeGetPositionX(layer),NodeGetPositionY(layer) + v.targetY)))
            local actionSeq = cc.EaseOut:create(spawnAction, rate)--由快至慢

            NodeRunAction(layer,actionSeq)
        end
    end
end

function Map:saveMapLayerScale()
    if not self.mSaveScale then
        self.mSaveScale = {}
    end
    self.mSaveScale.zoomScale = NodeGetScale(self.mZoomLayer)

    for k,v in pairs(self.mMapConfig.config.layer) do
        local layerConfig = v
        local layer = self.cachedZoomLayers[layerConfig.layerName]
        if layer then
            local currentScale = NodeGetScale(layer)
            self.mSaveScale[layerConfig.layerName] = currentScale
        end
    end
end

function Map:backToSaveMapLayerScale(time,callback)
    if not self.mSaveScale then return end

    local scaleTime = time or 0.5

    for k,v in pairs(self.mMapConfig.config.layer) do
        local layerConfig = v
        local layer = self.cachedZoomLayers[layerConfig.layerName]
        if layer then
            local destScale = self.mSaveScale[layerConfig.layerName]
            if destScale then
                if scaleTime > 0 then
                    local action = cc.Sequence:create(
                        cc.ScaleTo:create(scaleTime,destScale))
                    NodeStopAllActions(layer)
                    NodeRunAction(layer,action)
                else
                    layer:setScale(destScale)
                end
            end
        end
    end

    local zoomScale = self.mSaveScale.zoomScale
    if zoomScale then
        if scaleTime > 0 then
            local action = cc.Sequence:create(
                cc.ScaleTo:create(scaleTime,zoomScale),
                cc.CallFunc:create(function()
                self:setZoomScale(zoomScale)
                if callback then
                    callback()
                end
            end))
            NodeStopAllActions(self.mZoomLayer)
            NodeRunAction(self.mZoomLayer,action) 
        else
            self.mZoomLayer:setScale(zoomScale)
        end
    end
end

function Map:zoomLayerWithTime(time,met,flag)
    self:stopAllZoomLayerActions()
    local scaleRate = 1.0
    if flag == "battle" then
        local layerConfig = self:getLayerConfigByLine(2)
        if layerConfig then
            scaleRate = Constant.BattleLayerMinScale / layerConfig.minScale
        end
    end

    for k,v in pairs(self.mMapConfig.config.layer) do
        local layerConfig = v
        local layer = self.cachedZoomLayers[layerConfig.layerName]
        if layer then
            local currentScale = NodeGetScale(layer)
            local destScale = currentScale
            if layerConfig.minScale and layerConfig.maxScale then
                if met == "out" then
                    destScale = layerConfig.minScale
                    if flag == "battle" then
                        destScale = destScale * scaleRate
                    end
                elseif met == "in" then
                    destScale = layerConfig.maxScale
                end
                if time == 0 then
                    NodeSetScale(layer,destScale)
                else
                    local action = cc.Sequence:create(cc.ScaleTo:create(time,destScale))
                    NodeRunAction(layer,action)  
                end
            end
        end
    end
end

function Map:stopAllZoomLayerActions()
    for k,v in pairs(self.mMapConfig.config.layer) do
        local layerConfig = v
        local layer = self.cachedZoomLayers[layerConfig.layerName]
        if layer then
            NodeStopAllActions(layer)
        end
    end
end

function Map:stopCameraForBattle(stop)
    self.mStopCameraForBattle = stop
end

function Map:isStopCameraForBattle()
    return self.mStopCameraForBattle
end

function Map:setZoomScale(scale)
    MapManager:setMapScale(scale)
    NodeSetScale(self.mZoomLayer,scale)
    self:noScaleScale(1.0 / scale)
    app:saveValue(UserMapScaleString, scale)
end

function Map:setHaveMoveZoomOut(isZoomOut)
    self.mHaveMoveZoomOut = isZoomOut
end

function Map:mapTouchZoomIn(dt, speed)
    local maxScale = MapManager:getMaxScale()
    local deltaScale = speed * dt
    local targetScale = MapManager:getMapScale() + deltaScale
    -- 此处取两者较小的
    if targetScale > maxScale then targetScale = maxScale end
    self:setZoomScale(targetScale)
end

function Map:mapTouchZoomOut(dt, speed)
    local minScale = MapManager:getMinScale()
    local deltaScale = speed * dt
    local targetScale = MapManager:getMapScale() - deltaScale
    -- 此处取两者较大的 
    if targetScale < minScale then targetScale = minScale end
    self:setZoomScale(targetScale)
end

---
-- 强制场景回复原位
--
function Map:forceCameraZoomIn(funcOver,time,scale)
    local function overCall()
        if funcOver then
            funcOver()
        end
    end
    if self:isStopCameraForBattle() then
        overCall()
        return
    end
    if MapManager:isEventPauseRunCameraZoom() then
        return
    end
    MapManager:setForceCameraZoomOutToMin(false)
    MapManager:setForceCameraZoomIn(true)

    local fcTime = time or 0.5
    local destScale = scale or MapManager:getMaxScale()
    local function call()
        MapManager:setForceCameraZoomIn(false)
--        MapManager:setMapScale(destScale)
        self:setZoomScale(destScale)
        overCall()
    end
    NodeStopAllActions(self.mZoomLayer)
--    self:zoomLayerWithTime(fcTime,"in")
    local action = cc.Sequence:create(cc.ScaleTo:create(fcTime,destScale),cc.CallFunc:create(call))
    NodeRunAction(self.mZoomLayer,action)
end

function Map:forceCameraZoomOutToMin(time,funcOver)
    local function overCall()
        if funcOver then
            funcOver()
        end
    end
    if self:isStopCameraForBattle() then
        overCall()
        return
    end
    if MapManager:isEventPauseRunCameraZoom() then
        return
    end
    MapManager:setForceCameraZoomIn(false)
    MapManager:setForceCameraZoomOutToMin(true)

    local fcTime = time or 0.5
    local function call()
--        MapManager:setMapScale(MapManager:getMinScale())
        self:setZoomScale(MapManager:getMinScale())
        overCall()
    end
    NodeStopAllActions(self.mZoomLayer)
--    self:zoomLayerWithTime(fcTime,"out")
    local action = cc.Sequence:create(cc.ScaleTo:create(fcTime,MapManager:getMinScale()),cc.CallFunc:create(call))
    NodeRunAction(self.mZoomLayer,action)
end

function Map:forecCameraZoomOutToDest(time,dstScale,funcOver,flag)
    -- 缩小
    local function overCall()
        if funcOver then
            funcOver()
        end
    end
    if self:isStopCameraForBattle() and flag ~= "battle" then
        overCall()
        return
    end
    MapManager:pauseRunCameraZoomForEvent(true)

    local fcTime = time or 0.5
    local destScale = dstScale or MapManager:getMinScale()
    local function call()
        self:setZoomScale(dstScale)
        overCall()
    end
    NodeStopAllActions(self.mZoomLayer)
--    self:zoomLayerWithTime(fcTime,"out",flag)
    local action = cc.Sequence:create(cc.ScaleTo:create(fcTime,destScale),cc.CallFunc:create(call))
    NodeRunAction(self.mZoomLayer,action)
end

function Map:forceCameraZoomInToDest(time,dstScale,funcOver)
    -- 放大
    local function overCall()
        if funcOver then
            funcOver()
        end
    end
    if self:isStopCameraForBattle() then
        overCall()
        return
    end
    MapManager:pauseRunCameraZoomForEvent(true)
    
    local fcTime = time or 0.5
    local destScale = dstScale or MapManager:getMaxScale()
    local function call()
        self:setZoomScale(dstScale)
        overCall()
    end
    NodeStopAllActions(self.mZoomLayer)
--    self:zoomLayerWithTime(fcTime,"in")
    local action = cc.Sequence:create(cc.ScaleTo:create(fcTime,destScale),cc.CallFunc:create(call))
    NodeRunAction(self.mZoomLayer,action)
end

function Map:forceCameraZoomToDest(time,dstScale,funcOver)
    if dstScale > MapManager:getMaxScale() then
        dstScale = MapManager:getMaxScale()
    elseif dstScale < MapManager:getMinScale() then
        dstScale = MapManager:getMinScale()
    end
    if dstScale > MapManager:getMapScale() then
        self:forceCameraZoomInToDest(time,dstScale,funcOver)
    elseif dstScale < MapManager:getMapScale() then
        self:forecCameraZoomOutToDest(time,dstScale,funcOver)
    else
        NodeStopAllActions(self.mZoomLayer)
        local action = cc.Sequence:create(cc.DelayTime:create(time),cc.CallFunc:create(funcOver))
        NodeRunAction(self.mZoomLayer,action)
    end
end

function Map:forceCameraZoomToRunMax(resetPause,time,call)
    local rTime = time or 0.5
    local function callback()
        if resetPause then
            MapManager:pauseRunCameraZoomForEvent(false)
        end
        if call then
            call()
        end
    end
    self:forceCameraZoomToDest(rTime,MapManager:getMaxScale(),callback)
end

function Map:saveZoomLayerOriginalPos(pos)
    self.mZLOriginalPos = pos
end

function Map:getZoomLayerOriginalPos()
    return self.mZLOriginalPos
end

function Map:mapOffsetWithCenter(time,offsetx,offsety,dstScale)
    if self.mMapOffset then
        return
    end
    self.mMapOffset = true
    MapManager:pauseRunCameraZoomForEvent(true)
    self.mSaveZoomScale = MapManager:getMapScale()

    local function call()
        time = time or 0
        offsetx = offsetx or 0
        offsety = offsety or 0
        dstScale = dstScale or 2.0

        local x,y = NodeGetPosition(self.mZoomLayer)
        local dstx = x + offsetx
        local dsty = y + offsety

--        self:zoomLayerWithTime(time,"in")

        local action = cc.Sequence:create(cc.Spawn:create(
        cc.MoveTo:create(time,cc.p(dstx,dsty))
--        , cc.ScaleTo:create(time,dstScale)
        ), cc.CallFunc:create(function()
            self:setZoomScale(dstScale)
--            MapManager:setMapScale(dstScale)
        end))

        NodeStopAllActions(self.mZoomLayer)
        NodeRunAction(self.mZoomLayer,action)
    end

    self:forceCameraZoomToRunMax(false,0.1,call)
end

function Map:backMapOffsetToCenter(time,callback)
    local function excuteCall()
        if callback then
            callback()
        end
    end

    if not self.mMapOffset then
        excuteCall()
        return
    end
    MapManager:pauseRunCameraZoomForEvent(true)
    local function call()
        self.mMapOffset = false
        self:setZoomScale(self.mSaveZoomScale)
--        MapManager:setMapScale(self.mSaveZoomScale)
        MapManager:pauseRunCameraZoomForEvent(false)
        excuteCall()
    end

    local action = cc.Sequence:create(cc.Spawn:create(
        cc.MoveTo:create(time,self:getZoomLayerOriginalPos())
--        , cc.ScaleTo:create(time,self.mSaveZoomScale)
        ),
        cc.CallFunc:create(call))

    NodeStopAllActions(self.mZoomLayer)
    NodeRunAction(self.mZoomLayer,action)
end

function Map:initMapOffsetToCenter()
    self.mMapOffset = false
    self.mZoomLayer:setPosition(self:getZoomLayerOriginalPos())
end

function Map:getMapScale()
    local scale = self:getZoomLayerScale()
    local parent = self.mZoomLayer:getParent()
    while parent
    do
        scale = NodeGetScale(parent) * scale
        parent = parent:getParent()
    end
    return scale
end

function Map:getGroundScale(line)
    local ground = self.mGrounds[line]
    if ground then
        local scale = NodeGetScale(ground)
        local parent = ground:getParent()
        while parent
        do
            scale = NodeGetScale(parent) * scale
            parent = parent:getParent()
        end
        return scale
    end
    return 1
end

function Map:getZoomLayerScale()
    return NodeGetScale(self:getZoomLayer())
end

function Map:setCharacterToCenter(center)
    self.mCharacterToCenter = center
end

function Map:cameraZoomTo(params)
    self:setCharacterToCenter(true)

    local function callback()
        if params.callback then
            params.callback()
        end
    end

    local action
    if params.scale == 1 then
        action = cc.Sequence:create(
        cc.Spawn:create(cc.MoveTo:create(params.time,cc.p(0,0)),
        cc.ScaleTo:create(params.time,params.scale)),
        cc.CallFunc:create(callback))
    else
        action = cc.Sequence:create(
        cc.Spawn:create(cc.MoveBy:create(params.time,cc.p(params.mx,params.my)),
        cc.ScaleTo:create(params.time,params.scale)),
        cc.CallFunc:create(callback))
    end
    NodeRunAction(self,action)
    
    for k,v in pairs(self.mMapConfig.config.layer) do
        if v.fade then
            local layerName = v.layerName

            local fadeNode = self.cachedZoomLayers[layerName]:getChildByName("LayerBaseParallaxNode."..layerName):getChildByName(layerName)
            if fadeNode then
                local fadeAction 
                if params.scale == 1 then
                    fadeAction = cc.FadeTo:create(params.time,255)
                    
                else
                    fadeAction = cc.Sequence:create(cc.DelayTime:create(params.time),cc.FadeTo:create(0.1,255 * v.fade))
                end
                NodeRunAction(fadeNode,fadeAction)
            end
        end
    end
end

function Map:fadeNodeVisibility(visible)
    for k,v in pairs(self.mMapConfig.config.layer) do
        if v.fade then
            local layerName = v.layerName
            local layerRoot = self.cachedZoomLayers[layerName]
            if layerRoot then
                local fadeNode = layerRoot:getChildByName(layerName):getChildByName(layerName)
                if fadeNode then
                    NodeSetVisible(fadeNode,visible)
                end
            end
        end
    end

end

function Map:fadeNodeOpacity(time,back)
    for k,v in pairs(self.mMapConfig.config.layer) do
        if v.fade then
            local layerName = v.layerName
            local layerRoot = self.cachedZoomLayers[layerName]
            if layerRoot then
                local fadeNode = layerRoot:getChildByName("LayerBaseParallaxNode."..layerName):getChildByName(layerName)
                if fadeNode then
                    local fadeAction 
                    if back then
                        fadeAction = cc.FadeTo:create(time,255)
                    
                    else
                        fadeAction = cc.Sequence:create(cc.FadeTo:create(time,255 * v.fade))
                    end
                    NodeRunAction(fadeNode,fadeAction)
                end
            end
        end
    end
end

function Map:updateFrame(dt)
    self:adjustCamera(dt)
    self:adjustSurroundingSounds()
    self:updateMapMask(dt)



    local renderTexture = self._renderTexture
    if  renderTexture then
        self:setVisible(true)
        renderTexture:begin()
        self:visit()
        if self:getScreenLayer() then
            self:getScreenLayer():visit()
        end
        NodeFactory:getNameParent():visit()
        renderTexture:endToLua()
        self:setVisible(false)
    end
end

function Map:adjustSurroundingSounds()
    if self.mPauseAllSounds then
        return
    end
    local musicVolume = 1.0
    if self:getFocusCharacter() then
        local focusX = NodeGetPositionX(self:getFocusCharacter())
        for i = 1, self.mSoundVec:size() do
            local sound = self.mSoundVec:get(i)
            if focusX >= sound.sourcex - sound.range / 2 and focusX <= sound.sourcex + sound.range / 2 then
                local volume = 1.0 - MathAbs(focusX - sound.sourcex) / (sound.range / 2)
                if volume < 0 then
                    volume = 0
                end
                if volume > 1.0 then
                    volume = 1.0
                end
                if not sound.audioId then
                    sound.audioId = AM.play(sound.sound,true,AM.TagMusic)
                end
                if sound.audioId then
                    AM.setVolume(sound.audioId,volume)
                end
                musicVolume = 1.0 - volume
            else
                if sound.audioId then
                    AM.stop(sound.audioId)
                    sound.audioId = nil
                end
            end
        end
    end
end



---
-- 初始化camerax
--
function Map:initCamera()
    local destCameraX = 0
    local destCameraY = 0
    local focusPy = 0
    self.mMapOffsetY = 0

    local focusBattleActor = self:getFocusBattleActor()
    if focusBattleActor then
        local posX,posY = NodeToWorldPosition(focusBattleActor,0,0)
        posX,focusPy = NodeToLocalPosition(FieldManager:getMyCharacter():getParent(),posX, posY)
        destCameraX = posX - (display.cx)
    elseif self:getFocusNpc() then
        destCameraX = NodeGetPositionX(self:getFocusNpc()) - (display.width / 2)
        focusPy = NodeGetPositionY(self:getFocusNpc())
    elseif self:getFocusCharacter() then
        destCameraX = NodeGetPositionX(self:getFocusCharacter()) - (display.width / 2)
        focusPy = NodeGetPositionY(self:getFocusCharacter())
        self:setFocusCharacterPosition(self:getFocusCharacter():getPosition())
    end

    self.mMapOffsetY = self.mAdjustHeight - focusPy

    destCameraY = destCameraY - self.mMapOffsetY

    MapManager:setCameraX(destCameraX)
    MapManager:setCameraY(destCameraY)

    self:stopParallaxActions()
    self:setParallaxNodePos(0 - destCameraX,0 - destCameraY)

    self:initMapOffsetToCenter()
end

function Map:transCameraToDest(destCameraX,destCameraY,speed,dt,steady)
    -- if MapManager:isMapBorder() then
        if destCameraX < MapManager:getBorderLeftX() - display.width / 2 then
            destCameraX = MapManager:getBorderLeftX() - display.width / 2
        elseif destCameraX > MapManager:getBorderRightX() + display.width / 2 - display.width then
            destCameraX = MapManager:getBorderRightX() + display.width / 2 - display.width
        end
    -- end

    -- print(destCameraX, MapManager:getBorderLeftX(), display.cx)

    -- 镜头移动快慢的逻辑，暂时屏蔽掉

    -- local dstx = MathAbs(MapManager:getCameraX() - destCameraX)

    -- local maxDistX = display.width / 9
    
    -- if not self.mBackToCenter and dstx >= maxDistX then
    --     self.mBackToCenter = true
    -- end

    -- if self.mBackToCenter then
    --     speed = speed * 1.2
    --     steady = true
    -- end

    -- if self.mBackToCenter and dstx == 0 then
    --     self.mBackToCenter = false
    -- end
    

    -- if not steady then
    --     if dstx > maxDistX then
    --         speed = speed
    --     elseif dstx > maxDistX / 5 * 4 then
    --         speed = speed / 6 * 5
    --     elseif dstx > maxDistX / 5 * 3 then
    --         speed = speed / 6 * 4
    --     elseif dstx > maxDistX / 5 * 2 then
    --         speed = speed / 6 * 3
    --     elseif dstx > maxDistX / 5 then
    --         speed = speed / 6 * 2
    --     else
    --         speed = 2
    --     end
    -- end
    
    local cameraX = MapManager:getCameraX()
    if cameraX < destCameraX then
        cameraX = cameraX + speed * dt
        if cameraX > destCameraX then
            cameraX = destCameraX
        end
    elseif cameraX > destCameraX then
        cameraX = cameraX - speed * dt
        if cameraX < destCameraX then
            cameraX = destCameraX
        end
    end
    -- print(cameraX)
    MapManager:setCameraX(cameraX)

    local cameraY = MapManager:getCameraY()
    if cameraY < destCameraY then
        cameraY = cameraY + speed * dt
        if cameraY > destCameraY then
            cameraY = destCameraY
        end
    elseif cameraY > destCameraY then
        cameraY = cameraY - speed * dt
        if cameraY < destCameraY then
            cameraY = destCameraY
        end
    end
    MapManager:setCameraY(cameraY)
end

function Map:setFocusCharacterPosition(x,y)
    if not self.mFocusCharacterPosition then
        self.mFocusCharacterPosition = cc.p(x,y)
    else
        self.mFocusCharacterPosition.x = x
        self.mFocusCharacterPosition.y = y
    end

    FieldManager:setCharacterX(self.mFocusCharacterPosition.x)
    FieldManager:setCharacterY(self.mFocusCharacterPosition.y)
end

function Map:getFocusCharacterPosition()
    return self.mFocusCharacterPosition
end

-- Map adjust x这个属性表示战斗中镜头和玩家角色之间的偏移量
-- 远程职业需要镜头在是释放普通攻击时进行调整
function Map:setMapAdjudtX(mapAdjustX)
    self.mapAdjustX = mapAdjustX
end

function Map:getMapAdjustX()
    return self.mapAdjustX or 0
end

-- Map adjust speed这个属性表示战斗中镜头的跟随速度
-- 为了保持镜头稳定跟随，需要在战斗中设置为角色的移动速度
function Map:setMapAdjustSpeed(mapAdjustSpeed)
    self.mapAdjustSpeed = mapAdjustSpeed    
end

function Map:getMapAdjustSpeed()
    return self.mapAdjustSpeed or 0
end

function Map:getCameraAndFocusBattleActorDelta()
    local focusBattleActor = self:getFocusBattleActor()
    if focusBattleActor then
        local posX, posY = NodeToWorldPosition(focusBattleActor, 0, 0)
        posX, posY = NodeToLocalPosition(FieldManager:getMyCharacter():getParent(),posX, posY)
        posX = posX - display.cx
        return MapManager:getCameraX() - posX
    else
        return 0
    end
end

function Map:adjustCamera(dt)
    if (not MapManager:isPauseAdjustCamera() and not MapManager:isEventAutoAdjustCamera()) then
        local selfScale = self:getMapScale()

        local destCameraX = 0
        local destCameraY = 0
        local characterSpeed = 0
        local focusPy = 0

        local focusBattleActor = self:getFocusBattleActor()
        local focusNpc = self:getFocusNpc()
        local focusCharacter = self:getFocusCharacter()
        if focusBattleActor then
            -- 战斗中镜头跟随
            local posX,posY = NodeToWorldPosition(focusBattleActor,0,0)
            posX,focusPy = NodeToLocalPosition(FieldManager:getMyCharacter():getParent(),posX, posY)
            destCameraX = posX - display.cx
            destCameraX = destCameraX + self:getMapAdjustX()
 
            -- 镜头是否受战场边界影响，目前不受影响
            -- local leftClampX = self.mBattleLeftClampPosX
            -- local rightClampX = self.mBattleRightClampPosX
            -- if leftClampX and rightClampX then
                -- local width = display.width*Constant.BattleCameraClampSize
                -- if destCameraX < leftClampX - display.cx + width  then
                --     destCameraX = leftClampX - display.cx + width
                -- elseif destCameraX > rightClampX - display.cx - width then
                --     destCameraX = rightClampX - display.cx - width
                -- end
            -- end
            characterSpeed = self:getMapAdjustSpeed()

            if MathAbs(MapManager:getCameraX() - destCameraX) > display.width then
                -- 如果镜头与目标位置差距大于一屏，则直接跳转，不使用平滑移动
                MapManager:setCameraX(destCameraX)
            end
        elseif focusNpc then
            destCameraX = NodeGetPositionX(focusNpc) - (display.width / 2)

            characterSpeed = focusNpc:getSpeed()
            focusPy = NodeGetPositionY(focusNpc)
        elseif focusCharacter then
            destCameraX = NodeGetPositionX(focusCharacter) - (display.width / 2)

            characterSpeed = focusCharacter:getSpeed()-- / framePerSeconds
            focusPy = NodeGetPositionY(focusCharacter)
            self:setFocusCharacterPosition(NodeGetPosition(focusCharacter))
        end

        self.mMapOffsetY = self.mAdjustHeight - focusPy

        destCameraY = destCameraY - self.mMapOffsetY

        self:transCameraToDest(destCameraX,destCameraY,characterSpeed,dt)
        self:setParallaxNodePos(0 - MapManager:getCameraX(),0 - MapManager:getCameraY())
    end
end

function Map:initCustomNode(screenlayer)
    --添加自定义层
    self.mCustomLayer = cc.Layer:create()
    self.mParallaxNode:addChild(self.mCustomLayer,self.mMaxZ,cc.p(1,1),cc.p(0,0))

    if self.mMapConfig.config.custom then
        self.mMapConfig.config.custom({
            map = self,
            spriteNode = self.mCustomLayer,
            screenNode = screenlayer,
            mapWidth = MapManager:getMapWidth(),
            mapHeight = MapManager:getMapHeight()
        })
    end
end

function Map:setScreenLayer(screenLayer)
    self.mScreenLayer = screenLayer
end

function Map:getScreenLayer()
    return self.mScreenLayer
end

function Map:addWeatherToScreen(node,pos)
    if not self:getScreenLayer() or not node or not pos then return end 
    self:getScreenLayer():addChild(node)
    node:setPosition(pos)
end

function Map:addWeatherToGroundB(node,pos)
    if not node or not pos then return end
    if self.mAddGroundBNodes == nil then
        self.mAddGroundBNodes = {}
    end
    local groundB = self:getMapLayer("ground_B")
    if groundB then
        groundB:addChild(node)
        node:setPosition(pos)
        table.insert(self.mAddGroundBNodes,node)
    end
end

function Map:getMapLayer(layerName)
    local layer1 = self:getZoomLayer():getChildByName(layerName)
    if layer1 then
        local layer2 = layer1:getChildByName(layerName)
        if layer2 then
            local layer3 = layer2:getChildByName(layerName)
            if layer3 then
                return layer3
            end
        end
    end
    return nil
end

function Map:addWeatherToMapLayer(layerName,node,pos)
    if not layerName or not node or not pos then return end
    if self.mAddToLayerNodes == nil then
        self.mAddToLayerNodes = {}
    end
    local mapLayer = self:getMapLayer(layerName)
    if mapLayer then
        mapLayer:addChild(node)
        node:setPosition(pos)
        table.insert(self.mAddToLayerNodes,node)
    end
end

function Map:addWeatherParticleToScreen(path,pos,scale)
    if not path or not pos then return end
    if not cc.FileUtils:getInstance():isFileExist(path) then return end
    scale = scale or 1.0

    local ignore = cc.ParticleSystemQuad:create(path)
    local parent = cc.ParticleBatchNode:createWithTexture(ignore:getTexture())
    ignore:unscheduleUpdate()
    parent:setPosition(pos)
    self:getScreenLayer():addChild(parent)
    NodeSetScale(parent,scale)
    local emitter = cc.ParticleSystemQuad:create(path)
    parent:addChild(emitter)
end

function Map:clearWeatherNodes()
    if self:getScreenLayer() then
        self:getScreenLayer():removeAllChildren()
    end
    if self.mAddGroundBNodes then
        local groundB = self:getMapLayer("ground_B")
        if groundB then
            for i,v in ipairs(self.mAddGroundBNodes) do
                groundB:removeChild(v)
            end
        end
        self.mAddGroundBNodes = {}
    end

    if self.mAddToLayerNodes then
        for i,v in ipairs(self.mAddToLayerNodes) do
            v:removeFromParent()
        end
        self.mAddToLayerNodes = {}
    end

    if self.mNoScaleLayers then
        if self.mZoomLayer then
            for i,v in ipairs(self.mNoScaleLayers) do
                self.mZoomLayer:removeChild(v)
            end
        end
        self.mNoScaleLayers = {}
    end
end

function Map:fadeInWeatherNodes(callback,fTime)
    local fadetime = fTime
    local action = cc.Sequence:create(cc.FadeIn:create(fadetime))
    if self:getScreenLayer() then
        local children = self:getScreenLayer():getChildren()
        for i = 1,#children do
            local child = children[i]
            child:setCascadeOpacityEnabled(true)
            child:setOpacity(0)
            NodeRunAction(child,action:clone())
        end
    end
    if self.mAddGroundBNodes then
        local groundB = self:getMapLayer("ground_B")
        if groundB then
            for i,v in ipairs(self.mAddGroundBNodes) do
                v:setCascadeOpacityEnabled(true)
                v:setOpacity(0)
                NodeRunAction(v,action:clone())
            end
        end
    end
    if self.mAddToLayerNodes then
        for i,v in ipairs(self.mAddToLayerNodes) do
            v:setCascadeOpacityEnabled(true)
            v:setOpacity(0)
            NodeRunAction(v,action:clone())
        end
    end
    if self.mNoScaleLayers then
        if self.mZoomLayer then
            for i,v in ipairs(self.mNoScaleLayers) do
                v:setCascadeOpacityEnabled(true)
                v:setOpacity(0)
                NodeRunAction(v,action:clone())
            end
        end
    end
    local action1 = cc.Sequence:create(cc.DelayTime:create(fadetime + 0.1),cc.CallFunc:create(function()
        if callback then
            callback()
        end
    end))
    NodeRunAction(self,action1)
end

function Map:fadeOutWeatherNodes(callback,fTime)
    local fadetime = fTime
    local action = cc.Sequence:create(cc.FadeOut:create(fadetime))
    if self:getScreenLayer() then
        local children = self:getScreenLayer():getChildren()
        for i = 1,#children do
            local child = children[i]
            child:setCascadeOpacityEnabled(true)
            NodeRunAction(child,action:clone())
        end
    end
    if self.mAddGroundBNodes then
        local groundB = self:getMapLayer("ground_B")
        if groundB then
            for i,v in ipairs(self.mAddGroundBNodes) do
                v:setCascadeOpacityEnabled(true)
                NodeRunAction(v,action:clone())
            end
        end
    end
    if self.mAddToLayerNodes then
        for i,v in ipairs(self.mAddToLayerNodes) do
            v:setCascadeOpacityEnabled(true)
            NodeRunAction(v,action:clone())
        end
    end

    if self.mNoScaleLayers then
        if self.mZoomLayer then
            for i,v in ipairs(self.mNoScaleLayers) do
                v:setCascadeOpacityEnabled(true)
                NodeRunAction(v,action:clone())
            end
        end
    end
    local action1 = cc.Sequence:create(cc.DelayTime:create(fadetime + 0.1),cc.CallFunc:create(function()
        self:clearWeatherNodes()
        if callback then
            callback()
        end
    end))
    NodeRunAction(self,action1)
end

function Map:getConfigFadeImagePath()
    return self.mMapConfig.config.fadePath
end

function Map:buildPath(ground,pathNode,line,pathNodeParent)
    local children = pathNode:getChildren()
    local child
    local i = 0
    local pathPoints = {}

    for i = 0, #children - 1, 1 do
        child = children[i + 1]
        pathPoints[i + 1] = cc.p(NodeGetPositionX(child) * pathNodeParent:getScaleX(), NodeGetPositionY(child) * pathNodeParent:getScaleY())
    end

    table.sort(pathPoints,function(a,b)
        return a.x < b.x
    end)

    local len = #pathPoints
    local curNode = nil
    local nodes = {}
    for i = 2, len, 1 do
        local lp = pathPoints[i-1]
        local rp = pathPoints[i]
        local height = rp.y - lp.y

        --batch
        -- 1.两个点的落差<2  2.与前两个点落差的差<2
        if curNode and MathAbs(rp.y-curNode.maxY) < 2 and MathAbs(height-curNode.height) < 2 then
            curNode.maxX = rp.x
            curNode.maxY = rp.y
            curNode.length = rp.x - curNode.minX
            nodes[#nodes] = curNode
        else
            local node = {minX = lp.x, maxX = rp.x, minY = lp.y, maxY = rp.y, length = rp.x - lp.x, height = height}
            if MathAbs(lp.y - rp.y) < 1 then
                node.y = lp.y
            end
            table.insert(nodes,node)
            curNode = node
        end
    end

    for _,node in ipairs(nodes) do
        setmetatable(node,{__index = PathNodeM})
        MapManager:addPathNode(line, node)
    end

    -- if len > 1 then
    --     local minX = math.floor(pathPoints[1].x)
    --     local maxX = math.floor(pathPoints[len].x)
    --     MapManager:addLineData({line = line, minX = minX, maxX = maxX})
    -- end

    if line == Constant.BattleGroundLineNumber and len > 1 then
        local minX = math.floor(pathPoints[1].x)
        local maxX = math.floor(pathPoints[len].x)
        if SHOW_MAP_COORD then
            local debugLayer = cc.Layer:create()
            for i = 1,10000 do
                local x = minX + i * 100
                if x < maxX then
                    local y = math.floor(MapManager:getStandPointY(2,x))
                    -- local verticalBar = cc.DrawNode:create()
                    -- verticalBar:drawSegment(cc.p(x,0), cc.p(x,display.height), 1, cc.c4f(0.0, 1.0, 0.0, 1.0))
                    -- debugLayer:addChild(verticalBar)
                    local labelX = display.newTTFLabel({
                         text = "default",
--                         font = "Arial",
                         size = 20,
                    })
                    labelX:setPosition(cc.p(x,y))
                    labelX:setString(tostring(x) .. "\n" .. tostring(y))
                    debugLayer:addChild(labelX)
                else
                    break
                end
            end
            ground:addChild(debugLayer)
        end
    end


    --draw path
    --[[
    local way = cc.Node:create()
    local debugWay = cc.Layer:create()
    for i = 1, #vers - 1, 1 do
        local line = cc.DrawNode:create()
        line:drawSegment(vers[i], vers[i + 1], 1, cc.c4f(0.0, 1.0, 0.0, 1.0))
        debugWay:addChild(line)
    end
    ground:addChild(debugWay)
    ]]
end

function Map:addAnimationToMap(aniNode,zOrder)
    --该方法加的层 默认都不缩放
    local layer = cc.Layer:create()

    self.mZoomLayer:addChild(layer,zOrder)
    layer:addChild(aniNode)

    if self.mNoScaleLayers == nil then
        self.mNoScaleLayers = {}
    end
    table.insert(self.mNoScaleLayers,layer)
end

function Map:noScaleScale(scaleRate)
    if not self.mNoScaleLayers then
        return 
    end
    for i,v in ipairs(self.mNoScaleLayers) do
        local layer = v
        NodeSetScale(layer,scaleRate)
    end
end

function Map:stopAllLayerZoomAction()
    for k,v in pairs(self.mMapConfig.config.layer) do
        local layerConfig = v
        local layer = self.cachedZoomLayers[layerConfig.layerName]
        if layer then
            NodeStopAllActions(layer)
        end
    end
end

function Map:addBattleNodeToMap(node)
    local battleGround = self.mBattleGround
    if battleGround and self:getFocusCharacterPosition() then
        local layer = cc.Layer:create()
        self.mBattleLayer = layer
        layer:ignoreAnchorPointForPosition(false)
        layer:setAnchorPoint(cc.p(0.5,0))
        layer:addChild(node)
        battleGround:addChild(layer)
        layer:setPosition(self:getFocusCharacterPosition())
    end
end

function Map:removeBattleNodeFromMap()
    if not cc.isDead(self.mBattleLayer) then
        self.mBattleLayer:removeFromParent()
        self.mBattleLayer = nil
    end

    -- for k,v in pairs(self.mMapConfig.config.layer) do
    --     local layerConfig = v
    --     local layer = self.cachedZoomLayers[layerConfig.layerName]
    --     if layer then
    --         if layerConfig.layerName ~= "ground_M" then
    --             layer:setVisible(true)
    --         else
    --             --battleground
    --             local children = layer:getChildren()
    --             for i=1, layer:getChildrenCount() do
    --                 local child = children[i]
    --                 if child then
    --                     child:setVisible(true)
    --                     if child == self.mBattleParallaxNode then
    --                         local children = self.mBattleParallaxNode:getChildren()
    --                         for i=1, self.mBattleParallaxNode:getChildrenCount() do
    --                             local child2 = children[i]
    --                             if child2 then
    --                                 child2:setVisible(true)
    --                             end
    --                         end
    --                     end
    --                 end
    --             end
    --         end
    --     end
    -- end
end

function Map:getGroundMZorder()
    for k,v in pairs(self.mMapConfig.config.layer) do
        local layerConfig = v
        if layerConfig.layerName == "ground_M" then
            return tonumber(layerConfig.zOrder)
        end
    end
    return nil
end

function Map:createBattleMaskLayer()
    local battleMask = self.mGroudBLayer
    if battleMask and self:getFocusCharacterPosition() then
        local layer = cc.Layer:create()
        self.mBattleMaskLayer = layer
        layer:ignoreAnchorPointForPosition(false)
        layer:setAnchorPoint(cc.p(0.5,0))
        battleMask:addChild(layer)
        local pos = battleMask:convertToNodeSpace(cc.p(0,0))
        layer:setPosition(cc.p(pos.x,self:getFocusCharacterPosition().y))
        return self.mBattleMaskLayer
    end
    return nil
end

function Map:removeBattleMaskNodeFromMap()
    if self.mBattleMaskLayer then
        self.mBattleMaskLayer:removeFromParent()
        self.mBattleMaskLayer = nil
    end
end

function Map:getMapOffsetY()
    return self.mMapOffsetY
end

function Map:getLayerRatiox(layerName)
    for k,v in pairs(self.mMapConfig.config.layer) do
        if v.layerName == layerName then
            return v.ratiox
        end
    end

    return 1
end

function Map:getZoomLayer()
    return self.mZoomLayer
end

function Map:_addNpcToLine(line,npc,zOrder)
--    print("==================> really add npc", npc:getUid(), npc:getId(), line)
--    print(debug.traceback())
    self:getGroundByLine(line):addChild(npc,zOrder)
    npc:setLine(line)
    local npcResConfig = GD:queryNpcRes(npc:getId())
    local bossTag = (npcResConfig and npcResConfig.isBoss or 0)
    local scale = 1.0
    if tonumber(bossTag) == 1 then
        scale = MapManager:getGroundBossScale()
        npc:scaleTo(scale)
    else
        scale = MapManager:getGroundNpcScale()
        npc:scaleTo(scale)
    end
end

---
-- 添加npc到指定线路
--
function Map:addNpcToLine(line,npc,zOrder)
    if zOrder then
        zOrder = zOrder - 1
    else
        zOrder = -1
    end

    self:_addNpcToLine(line,npc,zOrder)
end

function Map:deleteNpcFromGround(npc,line)
    if not npc then return end
    if npc == self:getFocusNpc() then
        self:setFocusNpc(nil)
    end
    line = line or npc:getLine()
--    print("==================> really delete npc", npc:getUid(), npc:getId(), line)
    self:getGroundByLine(line):removeChild(npc)
end

---
-- 添加动画到指定线路
--
function Map:addAniToLine(aniId,line,aniNode,zOrder)
    local ani = {}
    ani.id = aniId
    ani.line = line
    self.mAniVec:add(ani)
    local zO = 0
    if zOrder then
        zO = zOrder
    end
    local name = ani.id .. "_" .. ani.line
    aniNode:setName(name)
    self:getGroundByLine(line):addChild(aniNode,zO)
end

function Map:removeAniByIdAndLine(aniId,line)
    local name = aniId .. "_" .. line
    local ground = self:getGroundByLine(line)
    if ground then
        ground:removeChildByName(name)
    end
end

function Map:removeAni(aniId)
    for i = 1,self.mAniVec:size() do
        local ani = self.mAniVec:get(i)
        if aniId == ani.id then
            self.mAniVec:removeAt(i)
            local name = ani.id .. "_" .. ani.line
            self:getGroundByLine(ani.line):removeChildByName(name)
            break
        end
    end
end

function Map:removeAllAni()
    for i = self.mAniVec:size(),1,-1 do
        local ani = self.mAniVec:get(i)
        self.mAniVec:removeAt(i)
        local name = ani.id .. "_" .. ani.line
        self:getGroundByLine(ani.line):removeChildByName(name)
    end
end

function Map:getGroundByLine(line)
    if self.mGrounds[tonumber(line)] then
        return self.mGrounds[tonumber(line)]
    else
        if self.mLines:size() >= 1 then
            local line1 = tonumber(self.mLines:get(1))
            return self.mGrounds[line1]
        end
    end

    return nil
end

function Map:addToGround(role,line,zOrder)
    local z = zOrder or 0
    local grounds = self.mGrounds
    local idx = tonumber(line)
    if grounds[idx] then
        grounds[idx]:addChild(role,z)
    else
        if self.mLines:size() >= 1 then
            line = tonumber(self.mLines:get(1))
            role:setLine(line)
            grounds[line]:addChild(role,z)
        end
    end
end

function Map:addCharacter(character,zOrder)
    local line = tonumber(character:getLine())

    local pathNode = self:getPathNode(line)
    if pathNode then
        local scale = Constant.HeroScale * pathNode.roleScale
        character:scaleTo(scale)
        if line == Constant.BattleGroundLineNumber then
            local layerConfig = self:getLayerConfigByLine(line)
            if layerConfig then
                if not layerConfig.minScale and not layerConfig.maxScale then
                    scale = scale / Constant.BattleMinScale
                end
            end
        end
        character:scaleTo(scale)
    else
        character:scaleTo(MapManager:getGroundRoleScale())
    end
    -- local scale = MapManager:getGroundRoleScale()
    -- character:scaleTo(scale)
    -- if line == Constant.BattleGroundLineNumber then
    --     local layerConfig = self:getLayerConfigByLine(2)
    --     if layerConfig then
    --         if not layerConfig.minScale and not layerConfig.maxScale then
    --             scale = scale / Constant.BattleMinScale
    --         end
    --     end
    -- end

    self:addToGround(character,line,zOrder)
end

function Map:reorderCharacter(character,zOrder)
    local line = tonumber(character:getLine())
    if self.mGrounds[line] then
        self.mGrounds[line]:reorderChild(character,zOrder)
    end
end

function Map:removeCharacter(character,cleanup)
    if not character then
        return
    end
    local tCleanup = true
    if cleanup == nil then
        tCleanup = true
        if character.removeAll then
            character:removeAll()
        end
    else
        tCleanup = cleanup
    end

    local line = tonumber(character:getLine())
    if self.mGrounds[line] then
        self.mGrounds[line]:removeChild(character,tCleanup)
    else
        for i = 1,self.mLines:size() do
            line = tonumber(self.mLines:get(i))
            if self.mGrounds[line] then
                self.mGrounds[line]:removeChild(character,tCleanup)
            end
        end
    end
end

---
--添加佣兵
--
function Map:addMercenary(mercenary)
    if not mercenary then return end
    local line = tonumber(mercenary:getLine())
    local scale = MapManager:getGroundMercenaryScale()
    mercenary:scaleTo(scale)
    self:addToGround(mercenary,line,1)
end

function Map:changeLine(character,newLine)
    local pathNode = self:getPathNode(newLine)
    if not pathNode then return end

    character:retain()
    self:removeCharacter(character,false)

    character:setLine(newLine)

    self:addCharacter(character,character:getLocalZOrder())
    character:rayCastFoothold(NodeGetPositionX(character))
    character:release()
end

function Map:resetFocus()
    if not FieldManager:getMyCharacter() then return end
    MapManager:pauseAdjustCamera(false)
    MapManager:pauseEventAutoAdjustCamera(false)
    if self:getFocusCharacter() ~= FieldManager:getMyCharacter() then
        self:setFocusCharacterNotInit(FieldManager:getMyCharacter())
    end
end

function Map:setFocusCharacter(character)
    self.mFocusCharacter = character
    if character then
        self:setFocusCharacterPosition(NodeGetPosition(character))
    end
end

function Map:setFocusCharacterForInit(character)
    self:setFocusNpc(nil)
    self:setFocusCharacter(character)
    self:initCamera()
end

function Map:setFocusCharacterNotInit(character)
    self:setFocusNpc(nil)
    self:setFocusCharacter(character)
end

function Map:getFocusCharacter()
    if cc.isDead(self.mFocusCharacter) then
        return nil
    end
    return self.mFocusCharacter
end

function Map:backNpcFocusToOldCharacter(time,callback)
    self.mFocusNpc = nil
    MapManager:pauseAdjustCamera(true)

    local selfScale = self:getMapScale()
    local destCameraX = 0
    local destCameraY = 0

    destCameraX = NodeGetPositionX(self:getFocusCharacter()) - (display.width / 2)
    
    local focusPy = NodeGetPositionY(self:getFocusCharacter())
    self.mMapOffsetY = self.mAdjustHeight - focusPy
    destCameraY = 0 - self.mMapOffsetY

    local function call()
        MapManager:setCameraX(destCameraX)
        MapManager:setCameraY(destCameraY)
        MapManager:pauseAdjustCamera(false)
        if callback then
            callback()
        end
    end
    self:parallaxNodesMoveTo(cc.p(0 - destCameraX,0 - destCameraY),time,call)
end

---
--设置屏幕焦点npc
--
function Map:setFocusNpc(npc)
    self.mFocusNpc = npc
    if self.mFocusCharacter and self.mFocusCharacter.stopMove then
        self.mFocusCharacter:stopMove()
    end
end

function Map:setFocusNpcForInit(npc)
    self:setFocusNpc(npc)
    self:initCamera()
end

function Map:getFocusNpc()
    if self.mFocusNpc and tolua.isnull(self.mFocusNpc) then
        return nil
    end
    return self.mFocusNpc
end

function Map:transitionFocusToNpc(npc,time,callback)
    self:setFocusNpc(npc)

    if not self.mFocusNpc then
        return
    end

    MapManager:pauseAdjustCamera(true)

    local selfScale = self:getMapScale()

    local destCameraX = 0
    destCameraX = NodeGetPositionX(self:getFocusNpc()) - display.width / 2

    local destCameraY = 0

    local focusPy = NodeGetPositionY(self:getFocusNpc())
    self.mMapOffsetY = self.mAdjustHeight - focusPy
    destCameraY = 0 - self.mMapOffsetY

    local function call()
        MapManager:setCameraX(destCameraX)
        MapManager:setCameraY(destCameraY)
        MapManager:pauseAdjustCamera(false)
        if callback then
            callback()
        end
    end

    self:parallaxNodesMoveTo(cc.p(0 - destCameraX,0 - destCameraY),time,call)
end


---
--设置屏幕焦点 战斗中的角色
--
function Map:setFocusBattleActor(actor, needInit)
    self.mFocusBattleActor = actor
    if needInit then
        --print("=========setFocusBattleActor init camera========")
        self:initCamera()
    end
    if UD.setting:isGenBattleStaticBgEnable() then
        if actor ~= nil then
            self.mBattleStaticLayerParent:performWithDelay(function()
                self:startgenBattleStaticBg()
            end, 0.5)
        else
            self:stopgenBattleStaticBg()
        end
    end
end

function Map:getFocusBattleActor()
    if cc.isDead(self.mFocusBattleActor) then
        return nil
    end
    return self.mFocusBattleActor
end

function Map:setBattleCameraClamp(leftClampPosX, rightClampPosX)
    self.mBattleLeftClampPosX = NodeToLocalPosition(FieldManager:getMyCharacter():getParent(),leftClampPosX, 0)
    self.mBattleRightClampPosX = NodeToLocalPosition(FieldManager:getMyCharacter():getParent(),rightClampPosX, 0)
end

function Map:setParallaxNodePos(posX,posY)
    if self.mEventParallaxNodesMoveTo then
        return
    end
    NodeSetPosition(self.mParallaxNode,posX,posY)
    for i = 1,self.mParallaxVec:size() do
        local parallaxNode = self.mParallaxVec:get(i)
        NodeSetPosition(parallaxNode,posX,posY)
    end
end

function Map:stopParallaxActions()
    if self.mEventParallaxNodesMoveTo then
        return
    end
    NodeStopAllActions(self.mParallaxNode)
    for i = 1,self.mParallaxVec:size() do
        local parallaxNode = self.mParallaxVec:get(i)
        NodeStopAllActions(parallaxNode)
    end
end

function Map:parallaxNodesMoveTo(pos,time,callback)
    local function callOver()
        if callback then
            callback()
        end
    end
    if self.mEventParallaxNodesMoveTo then
        callOver()
        return
    end

    if time == 0 then
        NodeStopAllActions(self.mParallaxNode)
        NodeSetPosition(self.mParallaxNode,pos)
        for i = 1,self.mParallaxVec:size() do
            local parallaxNode = self.mParallaxVec:get(i)
            NodeStopAllActions(parallaxNode)
            NodeSetPosition(parallaxNode,pos)
        end
        callOver()
    else
        local action = cc.Sequence:create(cc.MoveTo:create(time,pos),cc.CallFunc:create(callOver))
        NodeStopAllActions(self.mParallaxNode)
        NodeRunAction(self.mParallaxNode,action)
        local action1 = cc.Sequence:create(cc.MoveTo:create(time,pos))
        for i = 1,self.mParallaxVec:size() do
            local parallaxNode = self.mParallaxVec:get(i)
            NodeStopAllActions(parallaxNode)
            NodeRunAction(parallaxNode,action1:clone())
        end
    end
end

function Map:eventParallaxNodesMoveTo(pos,time,callback)
    self.mEventParallaxNodesMoveTo = true
    local function callOver()
        if callback then
            callback()
        end
        self.mEventParallaxNodesMoveTo = false
    end

    local action = cc.Sequence:create(cc.MoveTo:create(time,pos),cc.CallFunc:create(callOver))
    NodeStopAllActions(self.mParallaxNode)
    NodeRunAction(self.mParallaxNode,action)
    local action1 = cc.Sequence:create(cc.MoveTo:create(time,pos))
    for i = 1,self.mParallaxVec:size() do
        local parallaxNode = self.mParallaxVec:get(i)
        NodeStopAllActions(parallaxNode)
        NodeRunAction(parallaxNode,action1:clone())
    end
end

function Map:parallaxNodeMove(duration,dstPos)
    if self.mEventParallaxNodesMoveTo then
        return
    end
    local moveAction = cc.MoveTo:create(duration,dstPos)

    local moveEaseOut = cc.EaseSineOut:create(moveAction)

    NodeRunAction(self.mParallaxNode,moveEaseOut:clone())

    for i = 1,self.mParallaxVec:size() do
        local parallaxNode = self.mParallaxVec:get(i)
        NodeRunAction(parallaxNode,moveEaseOut:clone())
    end
end

function Map:getLineRatiox(line)
    if self.mLinesMoveRate[tonumber(line)] then
        return self.mLinesMoveRate[tonumber(line)]
    end

    return 1
end

function Map:getNameLabel(fontSize)
    local fSize = 30
    if fontSize then
        fSize = fontSize
    end
    local LabelName = display.newTTFLabel({
        text = " ",
--        font = "Arial",
        size = fSize,
        align = cc.TEXT_ALIGNMENT_CENTER -- 文字内部居中对齐
    })
    self:addChild(LabelName)
    LabelName:setParent(nil)
    LabelName:setName("name" .. math.random(1,1000))
    return LabelName
end

function Map:createChangeMapAnimation(path,armName,character)
    local Armature = app:getClass("Armature")
    local changeMapAnimation = Armature.create({
        path = path,
        armatureName = armName,
        animationName = "",
        skeletonName = armName
        })

    if character and changeMapAnimation then
        local fcx = NodeGetPositionX(character)
        local fcy = NodeGetPositionY(character)
        changeMapAnimation:setPosition(cc.p(fcx,fcy))
    end

    return changeMapAnimation
end

function Map:playChangeMapAnimation(path,armName,action,callOver,character,visible)
    local focusCharacter = self:getFocusCharacter()
    local line = 2
    local duration = 0.5
    if focusCharacter then
        line = focusCharacter:getLine()
    end

    local changeMapAnimation = self:createChangeMapAnimation(path,armName,character)
    if changeMapAnimation then
        local curSecond = os.time()
        local aniId = curSecond
        self:addAniToLine(aniId,line,changeMapAnimation,10000)
        changeMapAnimation:setVisible(visible)
        local function callback()
            if callOver then
                callOver()
            end
            self:removeAni(aniId)
        end
        local play = changeMapAnimation:playAni({name = action,playTimes = 1})
        duration = changeMapAnimation:getAniDuration(action)
        local sequence = cc.Sequence:create(cc.DelayTime:create(duration),cc.CallFunc:create(function() 
            callback()
        end))
        NodeRunAction(self,sequence)
    end
    return duration
end

function Map:playChangeMapStartAnimation(callOver,character,visible)
    local path = "armatures/effect/chuansong"
    local armName = "chuansong"
    local action = "go"
    local duration = self:playChangeMapAnimation(path,armName,action,callOver,character,visible)
    if character then
        local sequence = cc.Sequence:create(cc.FadeOut:create(duration),cc.CallFunc:create(function() 

        end))
        NodeRunAction(character,sequence)
        if character.isMySelf and character:isMySelf() then
            AM.playSoundById(9013)
        end
    end
end

function Map:playChangeMapEndAnimation(callOver,character)
    local path = "armatures/effect/chuansong"
    local armName = "chuansong"
    local action = "back"
    local duration = self:playChangeMapAnimation(path,armName,action,callOver,character)
    if character then
        character:setOpacity(0)
        local sequence = cc.Sequence:create(cc.FadeIn:create(duration),cc.CallFunc:create(function() 

        end))
        NodeRunAction(character,sequence)
        if character.isMySelf and character:isMySelf() then
            AM.playSoundById(9033)
        end
    end
end

function Map:multiplyColor(c)
    display.multiplyColor(self.mBackgroundLayer,c)
    display.multiplyColor(self.mRainLayer,c)
    for i = 1,self.mParallaxVec:size() do
        local node = self.mParallaxVec:get(i)
        if self.mBattleParallaxNode and self.mBattleParallaxNode == node then
            local children = self.mBattleParallaxNode:getChildren()
            for i=1, self.mBattleParallaxNode:getChildrenCount() do
                local child = children[i]
                if self.mBattleGround and child == self.mBattleGround then
                    -- display.setColor(child,c)
                else
                    display.multiplyColor(child,c)
                end
            end
        else
            display.multiplyColor(node,c)
        end
    end
end

function Map:divisionColor(c)
    display.divisionColor(self.mBackgroundLayer,c)
    display.divisionColor(self.mRainLayer,c)
    for i = 1,self.mParallaxVec:size() do
        local node = self.mParallaxVec:get(i)
        if self.mBattleParallaxNode and self.mBattleParallaxNode == node then
            local children = self.mBattleParallaxNode:getChildren()
            for i=1, self.mBattleParallaxNode:getChildrenCount() do
                local child = children[i]
                if self.mBattleGround and child == self.mBattleGround then
                    -- display.setColor(child,c)
                else
                    display.divisionColor(child,c)
                end
            end
        else
            display.divisionColor(node,c)
        end
    end
end

function Map:toBattleNormalColor()
    local v = self.mBattleNormalColor.r/255
    if self.multiplyColorValue and self.multiplyColorValue == v then
        return
    end
    self:toOriginColor()
    if not self.multiplyColorValue then
        local v = self.mBattleNormalColor.r/255
        self:multiplyColor(v)
        self.multiplyColorValue = v
    end
end

function Map:toBattleMoreMidBlack()
    local midColor = (self.mBattleNormalColor.r + self.mBattleMoreBlackColor.r)/2
    local v = midColor/255
    if self.multiplyColorValue and self.multiplyColorValue == v then
        return
    end
    self:toOriginColor()
    if not self.multiplyColorValue then    
        self:multiplyColor(v)
        self.multiplyColorValue = v
    end
end

function Map:toBattleFullBlack()
    local v = self.mBattleFullBlackColor.r/255
    if self.multiplyColorValue and self.multiplyColorValue == v then
        return
    end
    self:toOriginColor()
    if not self.multiplyColorValue then    
        self:multiplyColor(v)
        self.multiplyColorValue = v
    end
end

function Map:toBattleMoreBlack()
    local v = self.mBattleMoreBlackColor.r/255
    if self.multiplyColorValue and self.multiplyColorValue == v then
        return
    end
    self:toOriginColor()
    if not self.multiplyColorValue then    
        self:multiplyColor(v)
        self.multiplyColorValue = v
    end
end

function Map:toOriginColor()
    if self.multiplyColorValue then
        self:divisionColor(self.multiplyColorValue)
        self.multiplyColorValue=nil
    end
end

function Map:pauseAnimation(b)
    for i = 1,self.mParallaxVec:size() do
        local node = self.mParallaxVec:get(i)
        if b then
            _pause(node)
        else
            _resume(node)
        end
    end
    if b then
        _pause(self.mBackgroundLayer)
        _pause(self.mRainLayer)
    else
        _resume(self.mBackgroundLayer)
        _resume(self.mRainLayer)
    end
end


function Map:setFilter(filters,params)
--    print("====>Map:setFilter ",filters,params)
    local renderTexture = self._renderTexture
    if filters then
        if not renderTexture then
            renderTexture = cc.RenderTexture:create(display.width,display.height)
            renderTexture:retain()
            self._renderTexture = renderTexture
        end
        
        local sprite = self._filterSprite
        if sprite then
            sprite:removeFromParent()
            self._filterSprite = nil
        end

        sprite = display.newFilteredSprite(renderTexture:getSprite():getTexture(), filters, params)
        self._filterSprite = sprite
        self:getParent():addChild(sprite)
        sprite:setPosition(display.cx,display.cy)
        sprite:setScaleY(-1)
        
        self:setVisible(false)
    else
        
        if renderTexture then
            renderTexture:release()
            self._renderTexture = nil

            local sprite = self._filterSprite
            if sprite:getParent() then
                sprite:removeFromParent()
                self._filterSprite = nil
            end
        end
        self:setVisible(true)
    end
end

return Map